package cn.demoframe.test.core;

import cn.demoframe.test.model.Message;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import javax.servlet.http.HttpServletRequest;

/**
 * 全局Controller异常处理
 */
@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

	@ExceptionHandler(value = { Exception.class })
	public final ResponseEntity<Message> handleGeneralException(Exception ex, HttpServletRequest request) {
		logError(ex, request);

		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
		Message result = new Message();
		result.setResult(HttpStatus.INTERNAL_SERVER_ERROR.toString());
		result.setDetail(HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase());
		return new ResponseEntity<>(result, headers, HttpStatus.INTERNAL_SERVER_ERROR);
	}

	@Override
	protected ResponseEntity<Object> handleExceptionInternal(Exception ex, Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {
		logError(ex);
		if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) {
			request.setAttribute("javax.servlet.error.exception", ex, WebRequest.SCOPE_REQUEST);
		}

		String contentType = request.getHeader("Content-Type");
		if (StringUtils.containsIgnoreCase(contentType, MediaType.APPLICATION_JSON_VALUE)) {
			Message result = new Message();
			result.setResult(HttpStatus.INTERNAL_SERVER_ERROR.toString());
			result.setDetail(HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase());
			return new ResponseEntity<>((Object) result, headers, HttpStatus.INTERNAL_SERVER_ERROR);
		} else {
			return new ResponseEntity<>(body, headers, status);
		}
	}

	private void logError(Exception ex) {
		JSONObject obj = new JSONObject();
		obj.put("message", ex.getMessage());
		logger.error(obj.toJSONString(), ex);
	}

	private void logError(Exception ex, HttpServletRequest request) {
		JSONObject obj = new JSONObject();
		obj.put("message", ex.getMessage());
		obj.put("from", request.getRemoteAddr());
		String queryString = request.getQueryString();
		obj.put("path", queryString != null ? (request.getRequestURI() + "?" + queryString) : request.getRequestURI());
		logger.error(obj.toJSONString(), ex);
	}
}
